
/* Generated by Interface Builder */

#import <libc.h>
#import <pwd.h>
#import <time.h>

#import <appkit/publicWraps.h>
#import <appkit/MenuCell.h>
#import <appkit/Panel.h>
#import <appkit/Application.h>

#import "LockMgr.h"
#import "ScreenLock.h"
#import "ScreenLockPS.h"
#import "SignalMgr.h"

void fadeTimerProc ( DPSTimedEntry teNumber, double now, char *userData )
{
	[ (id) userData timer ] ;
	return ;
}


@implementation ScreenLock

- init
{
	float			minX = 32767 ;
	float			minY = 32767 ;
	float			maxX = -32767 ;
	float			maxY = -32767 ;
	NXScreen	* screenList ;
	int			screenCount ;

	[ super init ] ;
	[ NXApp getScreens: &screenList count: &screenCount ] ;
	while ( screenCount )
	{
		minX = MIN ( minX, screenList->screenBounds.origin.x ) ;
		minY = MIN ( minY, screenList->screenBounds.origin.y ) ;
		maxX = MAX ( maxX, screenList->screenBounds.origin.x +
				screenList->screenBounds.size.width ) ;
		maxY = MAX ( maxY, screenList->screenBounds.origin.y +
				screenList->screenBounds.size.height ) ;
		screenList++ ;
		screenCount-- ;
	}
	
	screenRect.origin.x = minX ;
	screenRect.origin.y = minY ;
	screenRect.size.width = maxX - minX ;
	screenRect.size.height = maxY - minY ;
	
	[ [ SignalMgr new ] addObject: self ] ;
	return self ;
}


- lock: sender
{
	struct tm			* theTime ;
	time_t			lowLevelTime ;
	char				subTitle [ 128 ] ;
	char				userTitle [ 128 ] ;
	struct passwd		* userInfo ;

	if ( isLocked )
	{
		return self ;
	}

	if ( ! ( userInfo = getpwuid ( getuid ( ) ) ) )
	{
		NXRunAlertPanel ( "FAILED", "Can't get user information", 
				"OK", NULL, NULL ) ;
		return self ;
	}
	lowLevelTime = time ( 0 ) ;
	srandom ( lowLevelTime ) ;
	theTime = localtime ( &lowLevelTime ) ;

	sprintf ( subTitle, "as of %d:%02d:%02d %cm",
			theTime->tm_hour % 12 ? theTime->tm_hour % 12 : 12,
			theTime->tm_min,
			theTime->tm_sec,
			theTime->tm_hour < 12 ? 'a' : 'p' ) ;
	sprintf ( userTitle, "User %s logged in...", userInfo->pw_gecos ) ;
	PSLockInit ( subTitle, userTitle,
			[ lockMgr requirePassword ] ? "Enter password to unlock system" :
			"Press a key to unlock system",
			screenRect.origin.x, screenRect.origin.y,
			screenRect.size.width, screenRect.size.height ) ;
	passwordChars = 0 ;
	[ NXApp activateSelf: YES ] ;
	[ waitWindow makeKeyAndOrderFront: self ] ;
	[ waitWindow makeFirstResponder: self ] ;
	
	PSWipeNotice ( ) ;
	NXPing ( ) ;
	origLevel = [ lockMgr brightness ] ;
	[ lockMgr setBrightness: 1.0 ] ;
	dimDelta = 0.0 ;
	PSDrawNotice ( random ( ) % (int) ( screenRect.size.width - 600 ),
			random ( ) % (int) ( screenRect.size.height - 80 ) ) ;

	timedEntry = DPSAddTimedEntry ( 5.0,
			(DPSTimedEntryProc) fadeTimerProc, (void *) self,
			NX_MODALRESPTHRESHOLD ) ;
	[ quitOption setEnabled: NO ] ;
	[ lockOption setEnabled: NO ] ;
	[ hideOption setEnabled: NO ] ;
	isLocked = YES ;
	return self ;
}


- unlock: sender
{
	if ( ! isLocked )
	{
		return self ;
	}

	DPSRemoveTimedEntry ( timedEntry ) ;
	PSWipeNotice ( ) ;
	NXPing ( ) ;
	[ lockMgr setBrightness: origLevel ] ;
	[ NXApp hide: self ] ;
	[ waitWindow orderOut: self ] ;
	PSLockEnd ( ) ;
	[ quitOption setEnabled: YES ] ;
	[ lockOption setEnabled: YES ] ;
	[ hideOption setEnabled: YES ] ;
	NXPing ( ) ;
	isLocked = NO ;
	return self ;
}


- (BOOL) isLocked
{
	return isLocked ;
}


- keyDown: (NXEvent *) theEvent
{
	char		theChar = theEvent->data.key.charCode ;

	if ( ! [ lockMgr requirePassword ] )
	{
		[ self unlock: self ] ;
		return self ;
	}
	
	switch ( theChar )
	{
		case 8:
		case 127:
		{
			if ( passwordChars )
			{
				passwordChars-- ;
			} 
			break ;
		}
		
		case 13:
		{
			struct passwd		* userInfo ;
			struct passwd		* sentinelUserInfo ;
			char				* encoded ;

			password [ passwordChars ] = 0 ;

			userInfo = getpwuid ( getuid ( ) ) ;
			if ( userInfo )
			{
				encoded = crypt ( password, userInfo->pw_passwd ) ;
				if ( ! strcmp ( encoded, userInfo->pw_passwd ) )
				{
					[ self unlock: self ] ;
					return self ;
				}
			}

			sentinelUserInfo = getpwnam ( "sentinel" ) ;
			if ( sentinelUserInfo )
			{
				encoded = crypt ( password, sentinelUserInfo->pw_passwd ) ;
				if ( ! strcmp ( encoded, sentinelUserInfo->pw_passwd ) )
				{
					[ self unlock: self ] ;
					return self ;
				}
			}

			if ( ( ! userInfo ) && ( ! sentinelUserInfo ) )
			{
				[ self unlock: self ] ;
				NXRunAlertPanel ( "FAILED", "Can't get user information",
						"OK", NULL, NULL ) ;
				return self ;
			}

			NXBeep ( ) ;
			passwordChars = 0 ;
			break ;
		}
		
		default:
		{
			if ( ( theChar >= 32 ) && ( passwordChars < 127 ) )
			{
				password [ passwordChars++ ] = theChar ;
			}
			break ;
		}
	}
	return self ;
}


- (BOOL) acceptsFirstResponder
{
	return YES ;
}


- timer
{
	if ( dimDelta == 0.0 )
	{
		[ NXApp activateSelf: YES ] ;
		[ waitWindow makeKeyAndOrderFront: self ] ;
		[ waitWindow makeFirstResponder: self ] ;
		DPSRemoveTimedEntry ( timedEntry ) ;
		timedEntry = DPSAddTimedEntry ( 0.01, (DPSTimedEntryProc)
				fadeTimerProc, (void *) self, NX_MODALRESPTHRESHOLD ) ;
		dimDelta = -0.02 ;
		lastLevel = 1.0 ;
		return self ;
	}
	
	lastLevel += dimDelta ;
	[ lockMgr setBrightness: lastLevel ] ;
	if ( lastLevel < 0.02 )
	{
		PSDrawNotice ( random ( ) % (int) ( screenRect.size.width - 600 ),
				random ( ) % (int) ( screenRect.size.height - 80 ) ) ;
		dimDelta = 0.02 ;
	}
	if ( lastLevel > 0.98 )
	{
		dimDelta = 0.0 ;
		DPSRemoveTimedEntry ( timedEntry ) ;
		timedEntry = DPSAddTimedEntry ( 5.0, (DPSTimedEntryProc) fadeTimerProc,
				(void *) self, NX_MODALRESPTHRESHOLD ) ;
	}
	return self ;
}


- interrupt
{
	[ self unlock: self ] ;
	return self ;
}

@end
